package com.youlu.campus.service.order.impl;

import com.alibaba.fastjson.JSON;
import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.common.utils.ExcelUtil;

import com.youlu.campus.entity.*;
import com.youlu.campus.entity.VO.req.OrderTipsImport;
import com.youlu.campus.entity.data.UniversityStatistics;
import com.youlu.campus.service.activity.ActivityService;
import com.youlu.campus.service.data.UniversityStatisticsService;
import com.youlu.campus.service.order.OrderInfoTipService;
import com.youlu.campus.service.platform.PlatformConfigService;
import com.youlu.campus.service.university.UniversityInfoService;
import com.youlu.campus.service.visitor.UserInfoExtendService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.ByteArrayInputStream;
import java.util.*;


@Slf4j
@Service
public class OrderInfoTipServiceImpl implements OrderInfoTipService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private ActivityService activityService;
    @Autowired
    private PlatformConfigService platformConfigService;
    @Autowired
    private UniversityStatisticsService universityStatisticsService;
    @Autowired
    private UniversityInfoService universityInfoService;

    @Autowired
    private UserInfoExtendService userInfoExtendService;

    @Override
    public OrderInfoTip find(String orderNo) {
        log.info(":>>> 开始查询订单提示语:{}", orderNo);
        Query query = new Query().addCriteria(Criteria.where("orderNo").is(orderNo));
        return mongoTemplate.findOne(query, OrderInfoTip.class);
    }

    @Override
    public boolean create(OrderInfoTip orderInfoTip) {
        log.info(":>>> 开始创建订单提示语:{}", JSON.toJSON(orderInfoTip));
        if (Objects.isNull(orderInfoTip) || StringUtils.isBlank(orderInfoTip.getOrderNo()) || StringUtils.isBlank(orderInfoTip.getTips())) {
            log.error(":>>> 订单提示语错误");
            throw new BusinessException("订单提示语错误");
        }
        orderInfoTip.setId(null);
        if (Objects.isNull(orderInfoTip.getCreatedTime())) {
            orderInfoTip.setCreatedTime(new Date());
        }
        mongoTemplate.insert(orderInfoTip);
        return true;
    }

    @Override
    public Map<String, Object> orderTpsImport(byte[] inputStream, String fileName, String activityId) {
        log.info("orderImport fileName {}", fileName);
        ActivityInfo activityInfo = activityService.findOne(activityId);
        Date date = new Date();
        if (Objects.isNull(activityInfo)) {
            log.error(":>>> 活动不存在:{}", activityId);
            throw new BusinessException("活动不存在");
        }
        try {
            Map<String, Object> result = new HashMap<>();
            List<OrderTipsImport> models = ExcelUtil.readData(new ByteArrayInputStream(inputStream),
                    OrderTipsImport.class);
            result.put("allCount", models.size());
            int matchCount = 0;
            int notMatchCount = 0;
            int errorInfo = 0;
            List<Integer> notMatchRows = new ArrayList<>();
            for (int i = 0; i < models.size(); i++) {
                OrderTipsImport model = models.get(i);
                log.info(":>>> 行:{} 订单号 {} 提示语", i, model.getOrderNo(), model.getTips());
                if (StringUtils.isBlank(model.getSubOrderNo()) || StringUtils.isBlank(model.getOrderNo()) || StringUtils.isBlank(model.getTips())) {
                    log.error(":>>> 导入参数错误:订单编号、子订单编号、提示语为空");
                    errorInfo++;
                    continue;
                }
                OrderInfoTip orderInfoTip = this.find(model.getOrderNo(), model.getSubOrderNo());
                if (Objects.isNull(orderInfoTip)) {
                    orderInfoTip = new OrderInfoTip();
                    orderInfoTip.setOrderNo(model.getOrderNo());
                    orderInfoTip.setTips(model.getTips());
                    orderInfoTip.setActivityId(activityId);
                    orderInfoTip.setActivityName(activityInfo.getName());
                    orderInfoTip.setCreatedTime(date);
                    orderInfoTip.setNewed(model.getNewed());
                    orderInfoTip.setSubOrderNo(model.getSubOrderNo());
                    this.create(orderInfoTip);
                } else {
                    orderInfoTip.setTips(model.getTips());
                    orderInfoTip.setNewed(model.getNewed());
                    orderInfoTip.setUpdatedTime(date);
                    this.update(orderInfoTip);
                }
                matchCount++;
            }
            result.put("matchCount", matchCount);
            result.put("notMatchCount", notMatchCount);
            result.put("notMatchRows", notMatchRows);
            result.put("errorInfo", errorInfo);
            result.put("tips", "列序号从0(A列)开始,第1列订单编号(A列)、第2列(B列)提示语不能为空!");
            return result;
        } catch (Exception e) {
            log.error("orderImport error fileName {},{}", fileName, e);
            return null;
        }
    }

    @Override
    public boolean update(OrderInfoTip orderInfoTip) {
        log.info(":>>> 开始修改订单提示语:{}", JSON.toJSON(orderInfoTip));
        if (Objects.isNull(orderInfoTip) || StringUtils.isBlank(orderInfoTip.getId())) {
            log.error(":>>> 订单提示语错误");
            throw new BusinessException("订单提示语错误");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(orderInfoTip.getId()));
        Update update = new Update();
        update.set("tips", orderInfoTip.getTips());
        if(Objects.nonNull(orderInfoTip.getUpdatedTime())){
            update.set("updatedTime", orderInfoTip.getUpdatedTime());
        }else {
            update.set("updatedTime", new Date());
        }
        if (Objects.nonNull(orderInfoTip.getNewed())) {
            update.set("newed", orderInfoTip.getNewed());
        }
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, OrderInfoTip.class);
        log.info(":>>> 更新订单提示语:{},结果为:{}", orderInfoTip.getId(), updateResult.getModifiedCount());
        return true;
    }

    @Override
    public OrderInfoTip find(String orderNo, Boolean newed) {
        log.info(":>>> 开始查询订单提示语:{},newed:{}", orderNo, newed);
        Query query = new Query().addCriteria(Criteria.where("orderNo").is(orderNo).and("newed").is(newed));
        return mongoTemplate.findOne(query, OrderInfoTip.class);
    }

    @Override
    public OrderInfoTip find(String orderNo, String subOrderNo) {
        log.info(":>>> 开始查询订单提示语:{},子订单编号:{}", orderNo, subOrderNo);
        Query query = new Query().addCriteria(Criteria.where("orderNo").is(orderNo).and("subOrderNo").is(subOrderNo));
        return mongoTemplate.findOne(query, OrderInfoTip.class);
    }

    @Override
    public OrderInfoTip find(String orderNo, String subOrderNo, Boolean newed) {
        log.info(":>>> 开始查询订单提示语:{},newed:{}", orderNo, newed);
        Query query = new Query().addCriteria(Criteria.where("orderNo").is(orderNo).and("newed").is(newed).and(
                "subOrderNo").is(subOrderNo));
        return mongoTemplate.findOne(query, OrderInfoTip.class);
    }

    /**
     * 设置子订单提示语
     *
     * @param orderInfo
     */
    @Override
    public void setSubOrderTips(OrderInfo orderInfo) {
        if (Objects.isNull(orderInfo) || StringUtils.isBlank(orderInfo.getStatus()) || CollectionUtils.isEmpty(orderInfo.getOOrderInfos())) {
            log.info(":>>>  设置子订单编号错误:订单信息、订单状态、子订单集合为空");
            return;
        }
        if ("item".equals(orderInfo.getCategory())) {
            return;
        }
        PlatformConfig platformConfig = platformConfigService.find();
        for (OOrderInfo oOrderInfo : orderInfo.getOOrderInfos()) {
            log.info(":>>> 子订单:{} 订单中的提示语:{}", oOrderInfo.getOOrderNo(), oOrderInfo.getTips());
            //退款中 、退款已完成、已发货 、已收获后不显示订单发货提示语
            if("6".equals(orderInfo.getStatus())||"9".equals(orderInfo.getStatus())){
                oOrderInfo.setTips("");
                log.error("【订单提示语】订单提示语->{}",orderInfo.getOrderNo());
            }else{
                this.setOOrderTips(orderInfo, platformConfig, oOrderInfo);
            }
        }
    }

    @Override
    public void setOOrderTips(OrderInfo orderInfo, PlatformConfig platformConfig, OOrderInfo oOrderInfo) {
        CaInfo itemInfo = null;
        if (StringUtils.isNotBlank(oOrderInfo.getItemInfoId())) {
            Query queryItem = new Query().addCriteria(Criteria.where("id").is(oOrderInfo.getItemInfoId()));
            itemInfo = mongoTemplate.findOne(queryItem, CaInfo.class);
        }
        log.info("【订单提示语】orderNo - > {} 匹配 tips", oOrderInfo.getOOrderNo());
        String tips = "";
        if (StringUtils.isNotBlank(orderInfo.getRefundStatus())) {
//            退款状态,0:未退款,1:退款申请,2:退款中,3:退款完成,4:待返货,7:部分退款中
            switch (orderInfo.getRefundStatus()) {
                case "2":
                    tips = platformConfig.getRefundingOrderTips();
                    oOrderInfo.setTips(tips);
                    return;
                case "3":
                    tips = platformConfig.getRefundedOrderTips();
                    oOrderInfo.setTips(tips);
                    return;
                default:
            }
        }

        String status = oOrderInfo.getStatus();
        // 状态,0:待付款,1:已付款,2:制作中,3:待发货,4:待收货,5:已收货,6:订单完成,7:订单关闭,8:售后中,9:退款中,10:部分已发货
        if (StringUtils.isBlank(status)) {
            log.info(":>>> 子订单:{} 状态为空,使用主订单状态:{}", oOrderInfo.getId(), orderInfo.getStatus());
            status = orderInfo.getStatus();
        }
        if (StringUtils.isBlank(status)) {
            log.info(":>>> 子订单:{} 状态为空,使用主订单状态为空", oOrderInfo.getId());
            return;
        }
        log.info("【订单提示语】orderNo - > {} status -> {}", oOrderInfo.getOOrderNo(), status);
        switch (status) {
            case "0": {
                if (Objects.nonNull(itemInfo)) {
                    tips = setSubOrderTipsForOverbought(itemInfo, oOrderInfo, tips);
                }
                if (StringUtils.isBlank(tips)) {
//                    tips = "亲，您的订单目前正在专属定制中，需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";
                    tips = "无";
                }
            }
            break;
            case "1": {
//                tips = "亲，您的订单需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";
                tips = "无";
                if (Objects.nonNull(orderInfo.getPayTime())) {
                    if ((new Date().getTime() - orderInfo.getPayTime().getTime()) > 12 * 3600 * 1000L) {
                        orderInfo.setStatus("2");
                        oOrderInfo.setStatus("2");
//                        tips = "亲，您的订单目前正在专属定制中，需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";
                        tips = "无";
                    }
                }
                if (StringUtils.isNotBlank(oOrderInfo.getTips())) {
                    tips = oOrderInfo.getTips();
                } else {
                    if (Objects.nonNull(itemInfo)) {
                        tips = setSubOrderTipsForOverbought(itemInfo, oOrderInfo, tips);
                    }
                }
                OrderInfoTip orderInfoTip = this.find(orderInfo.getOrderNo(), oOrderInfo.getOOrderNo());
                if (Objects.nonNull(orderInfoTip) && StringUtils.isNotBlank(orderInfoTip.getTips())) {
                    tips = orderInfoTip.getTips();
                    log.info(":>>> 订单:{}在 提示语言信息中", orderInfo.getOrderNo(), tips);
                }
            }
            break;

            case "2": {
                tips = "无";
//                tips = "亲，您的订单目前正在专属定制中，需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";
                if (StringUtils.isNotBlank(oOrderInfo.getTips())) {
                    tips = oOrderInfo.getTips();
                } else {
                    if (Objects.nonNull(itemInfo)) {
                        tips = setSubOrderTipsForOverbought(itemInfo, oOrderInfo, tips);
                    }
                }
                OrderInfoTip orderInfoTip = this.find(orderInfo.getOrderNo(), oOrderInfo.getOOrderNo());
                if (Objects.nonNull(orderInfoTip) && StringUtils.isNotBlank(orderInfoTip.getTips())) {
                    tips = orderInfoTip.getTips();
                    log.info(":>>> 订单:{}在 提示语言信息中", orderInfo.getOrderNo(), tips);
                }
            }
            break;
            case "3": {
                if (StringUtils.isNotBlank(oOrderInfo.getTips())) {
                    tips = oOrderInfo.getTips();
                } else {
                    if (Objects.nonNull(itemInfo)) {
                        tips = setSubOrderTipsForOverbought(itemInfo, oOrderInfo, tips);
                    }
                }
                OrderInfoTip orderInfoTip = this.find(orderInfo.getOrderNo(), oOrderInfo.getOOrderNo());
                if (Objects.nonNull(orderInfoTip) && StringUtils.isNotBlank(orderInfoTip.getTips())) {
                    tips = orderInfoTip.getTips();
                    log.info(":>>> 订单:{}在 提示语言信息中", orderInfo.getOrderNo(), tips);
                }
            }
            break;
            case "4": {
                OrderInfoTip orderInfoTip = this.find(orderInfo.getOrderNo(), oOrderInfo.getOOrderNo(), Boolean.TRUE);
                if (Objects.nonNull(orderInfoTip) && StringUtils.isNotBlank(orderInfoTip.getTips())) {
                    tips = orderInfoTip.getTips();
                    log.info(":>>> 订单:{}在 提示语言信息中", orderInfo.getOrderNo(), tips);
                } else {
                    if (StringUtils.isNotBlank(oOrderInfo.getLogisticsNo())) {
                        tips = "你的订单已发货，请注意查收，可点击下方按钮查看物流详情，若查看不到物流详情，是因为还在扫描出库中，请耐心等待3-5天后再次点击查看";
                    }
                }
            }
            break;
            default:
                break;
        }
        oOrderInfo.setTips(tips);
        log.info(":>>> 子订单:{} 的提示语:{}", oOrderInfo.getOOrderNo(), tips);
    }

    @Override
    public void initUserInfo() {
        log.info("开始初始化用户账户地址数据");
        Integer pageNo = 1;
        Integer pageSize = 10000;
        while (true) {
            PageRequest pageRequest = PageRequest.of(pageNo - 1, pageSize);
            Query query = new Query();
            query.addCriteria(Criteria.where("status").ne("0"));
            List<OrderInfo> list = this.mongoTemplate.find(query.with(pageRequest), OrderInfo.class);
            if (CollectionUtils.isEmpty(list)) {
                break;
            }
            list.stream().forEach(orderInfo -> {
                UserPO currentUser = new UserPO();
                currentUser.setId(orderInfo.getAccountInfoId());
                currentUser.setProvince(orderInfo.getProvince());
                currentUser.setArea(orderInfo.getArea());
                currentUser.setCity(orderInfo.getCity());
                currentUser.setFullAddress(orderInfo.getAddress());
                userInfoExtendService.saveOrUpdate(currentUser);
            });
            pageNo++;
        }
        log.info("结束初始化用户账户地址数据");
    }

    @Override
    public void setOrderTipsNes(OrderInfo orderInfo) {
        if (Objects.isNull(orderInfo) || StringUtils.isBlank(orderInfo.getStatus())) {
            log.error(":>>> 订单信息或订单状态为空");
            return;
        }
        String tips = "";
        if (StringUtils.isNotBlank(orderInfo.getRefundStatus())) {
            switch (orderInfo.getRefundStatus()) {
                case "2":
                    tips = "退款申请成功，原订单金额将于1-3个工作日到账，注意查收！";
                    orderInfo.setTips(tips);
                    return;
                case "3":
                    tips = "用户申请退款,退款完成,请查看微信账单!";
                    orderInfo.setTips(tips);
                    return;
                default:
                    break;
            }
        }

        if ("1".equals(orderInfo.getStatus())) {
            tips = "亲，您的订单需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";
            if (Objects.nonNull(orderInfo.getPayTime())) {
//                Date d = TimeUtils.getDayEndTime(orderInfo.getPayTime());
//                Date d = new Date(orderInfo.getPayTime().getTime() + 12 * 3600 * 1000L);
                if ((new Date().getTime() - orderInfo.getPayTime().getTime()) > 12 * 3600 * 1000L) {
                    orderInfo.setStatus("2");
                    tips = "亲，您的订单目前正在专属定制中，需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";
                }
            }
            OrderInfoTip orderInfoTip = this.find(orderInfo.getOrderNo());
            if (Objects.nonNull(orderInfoTip) && StringUtils.isNotBlank(orderInfoTip.getTips())) {
                tips = orderInfoTip.getTips();
                log.info(":>>> 订单:{}在 提示语言信息中", orderInfo.getOrderNo(), tips);
            }

        } else if ("2".equals(orderInfo.getStatus())) {
            OrderInfoTip orderInfoTip = this.find(orderInfo.getOrderNo());
            if (Objects.nonNull(orderInfoTip) && StringUtils.isNotBlank(orderInfoTip.getTips())) {
                tips = orderInfoTip.getTips();
                log.info(":>>> 订单:{}在 提示语言信息中", orderInfo.getOrderNo(), tips);
            }
            if (StringUtils.isBlank(tips)) {
                tips = "亲，您的订单目前正在专属定制中，需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";

            }

        } else if ("3".equals(orderInfo.getStatus())) {
            tips = "亲，您的订单目前正在专属定制中，需经过审核、制作、工艺加工、包装出库等流程。周期一般为5-7个工作日，请耐心等待，发货后会有物流单号在这里显示哦~";
        } else if ("4".equals(orderInfo.getStatus())) {
            OrderInfoTip orderInfoTip = this.find(orderInfo.getOrderNo(), Boolean.TRUE);
            if (Objects.nonNull(orderInfoTip) && StringUtils.isNotBlank(orderInfoTip.getTips())) {
                tips = orderInfoTip.getTips();
                log.info(":>>> 订单:{}在 提示语言信息中", orderInfo.getOrderNo(), tips);
            } else {
                tips = "您的订单已经发货，请注意查收！可点击下方按钮查看物流进度";

            }
        }
        orderInfo.setTips(tips);
    }

    @Override
    public void statisticsActivity(Long total) {
        log.info(":>>>  开始统计订单:{}", total);
        Integer pageSize = 10000;
        Integer pages = total.intValue() / pageSize + 1;
        Query query = new Query().addCriteria(Criteria.where("status").ne("0"));
        for (int i = 0; i < pages + 1; i++) {
            log.info(":>>> 开始处理第:{} 页 ", i);
            query.skip((i - 1) * pageSize);
            query.limit(pageSize);
            List<OrderInfo> datas = mongoTemplate.find(query, OrderInfo.class);
            if (CollectionUtils.isEmpty(datas)) {
                log.info(":>>> 第:{} 页数据为空 ", i);
                continue;
            }
            for (OrderInfo up : datas) {
                if (StringUtils.isBlank(up.getActivityId()) || StringUtils.isBlank(up.getMobile()) || StringUtils.isBlank(up.getUniversityId()) || StringUtils.isBlank(up.getOrderNo())) {
                    log.info(":>>> 活动ID、手机号、大学ID、订单编号为空");
                    continue;
                }
                Query query1 =
                        new Query().addCriteria(Criteria.where("mobile").is(up.getMobile()).and("orderNo").ne(up.getOrderNo()));
                Long t = mongoTemplate.count(query1, OrderInfo.class);
                log.info(":>>> 手机号:{},订单编号:{} 购买数量:{}", up.getMobile(), up.getOrderNo(), t);
                Long key = t + 1L;
                UniversityStatistics universityStatistics =
                        universityStatisticsService.findByUniversityId(up.getUniversityId());
                if (Objects.isNull(universityStatistics)) {
                    universityStatistics = new UniversityStatistics();
                    universityStatistics.setUniversityId(up.getUniversityId());
                    universityStatistics.setPayNum(1L);
                    universityStatistics.getRepurchaseDatas().put(key.intValue(), 1L);
                    UniversityInfo universityInfo = universityInfoService.findOne(up.getUniversityId());
                    if (Objects.nonNull(universityInfo)) {
                        universityStatistics.setUniversityName(universityInfo.getName());
                    }
                    if (Objects.nonNull(up.getTotalFee())) {
                        Double gmv = Double.valueOf(up.getTotalFee() + "") / 100D;
                        universityStatistics.setGmv(gmv);
                        //     * 退款状态,0:未退款,1:退款申请,2:退款中,3:退款完成,4:待返货,7:部分退款中
                        if ("1".equals(up.getRefundStatus()) || "2".equals(up.getRefundStatus()) || "3".equals(up.getRefundStatus())) {
                            universityStatistics.setRefundGmv(gmv);
                            universityStatistics.setRefundNum(1L);
                        }
                    }
                    universityStatisticsService.create(universityStatistics);
                    log.info(":>>> 大学:{} 统计不存在,新增:{}", up.getUniversityId(), JSON.toJSON(universityStatistics));
                    continue;
                }
                universityStatistics.setPayNum(1L);
                universityStatistics.setSignUpNum(0L);
                universityStatistics.setSignUpDatas(null);
                if (universityStatistics.getRepurchaseDatas().containsKey(key.intValue())) {
                    universityStatistics.getRepurchaseDatas().put(key.intValue(),
                            universityStatistics.getRepurchaseDatas().get(key.intValue()) + 1L);
                } else {
                    universityStatistics.getRepurchaseDatas().put(key.intValue(), 1L);
                }
                if (Objects.nonNull(up.getTotalFee())) {
                    Double gmv = Double.valueOf(up.getTotalFee() + "") / 100D;
                    universityStatistics.setGmv(gmv);
                    //     * 退款状态,0:未退款,1:退款申请,2:退款中,3:退款完成,4:待返货,7:部分退款中
                    if ("1".equals(up.getRefundStatus()) || "2".equals(up.getRefundStatus()) || "3".equals(up.getRefundStatus())) {
                        universityStatistics.setRefundGmv(gmv);
                        universityStatistics.setRefundNum(1L);
                    }
                }
                log.info(":>>> 大学:{} 统计存在,修改:{}", up.getUniversityId(), JSON.toJSON(universityStatistics));
                universityStatisticsService.update(universityStatistics);
            }
        }
    }

    /**
     * 设置订单提示语,针对对超卖订单
     *
     * @param itemInfo
     * @param oOrderInfo
     */
    private String setSubOrderTipsForOverbought(CaInfo itemInfo, OOrderInfo oOrderInfo, String defaultTips) {
        log.info(":>>> 开始设置子订单提示语:{},{},商品:{}", oOrderInfo.getOOrderNo(), defaultTips, itemInfo == null ? null :
                itemInfo.getId());
        String tips = defaultTips;
        if (Objects.isNull(itemInfo)) {
            return tips;
        }
        if (Boolean.TRUE.equals(oOrderInfo.getOverbought()) && StringUtils.isNotBlank(itemInfo.getNoStockTips())) {
            tips = itemInfo.getNoStockTips();
            return tips;
        }
        if (StringUtils.isNotBlank(itemInfo.getInStockTips())) {
            tips = itemInfo.getInStockTips();
        }
        return tips;
    }
}
